#ifndef __BASIC_LIST_H__
#define __BASIC_LIST_H__

#include <basic/misc.h>

__BEGIN_DECLS

/*----- 通用双向链表 -----*/
struct listp_link
{/*{{{*/
    struct listp_link *prev, *next;
};/*}}}*/

/*
 * 获取真实节点
 */
#define listp_entry(_ptr, _type, _member) \
((_type *)((char *)(_ptr)-(unsigned long)(&((_type *)0)->_member)))

/*
 * 链表是否为空
 */
#define listp_is_empty(_head)    \
((_head)->next == (_head))

/*
 * 链表初始化
 */
#define listp_init(_head)    \
(_head)->next=(_head)->prev=(_head)

/*
 * 释放链表
 */
#define listp_free(_head, _type, _link)                         \
do                                                              \
{                                                               \
    _type *_real;                                               \
    while(!listp_is_empty(_head))                               \
    {                                                           \
        _real=listp_entry((_head)->next, _type, _link);         \
        listp_del((_head)->next);                               \
        free(_real);                                            \
    }                                                           \
} while(0)

/*
 * 释放链表并释放节点中某个成员
 */
#define listp_free_memb(_head, _type, _link, _memb)             \
do                                                              \
{                                                               \
    _type *_real;                                               \
    while(!listp_is_empty(_head))                               \
    {                                                           \
        _real=listp_entry((_head)->next, _type, _link);         \
        listp_del((_head)->next);                               \
        if(_real->_memb)  free(_real->_memb);                   \
        free(_real);                                            \
    }                                                           \
} while(0)

/*
 * 在某个节点后加入新节点
 */
extern void
listp_add(
        struct listp_link *new_link,    /* [IN,OUT] 新节点连接件 */
        struct listp_link *prev_link    /* [IN,OUT] 前一节点连接件 */
        );

/*
 * 在链表末加入新节点
 */
extern void
listp_add_tail(
        struct listp_link *new_link,	/* [IN,OUT] 新节点连接件 */
        struct listp_link *head_link	/* [IN,OUT] 链表头 */
        );

/*
 * 从链表中删除节点
 */
extern void
listp_del(
        struct listp_link *delete_link	/* [IN,OUT] 删除节点 */
        );

/*
 * 把一链表中全部节点转移给另一空链表
 */
extern void
listp_takeover(
        struct listp_link *releaser_head,	/* [IN,OUT] 释放链表头 */
        struct listp_link *receiver_head	/* [IN,OUT] 接受链表头 */
        );

/*
 * 把一链表中全部节点附加到另一链表末尾
 */
extern void
listp_append(
        struct listp_link *append_head,		/* [IN,OUT] 释放链表头 */
        struct listp_link *dest_head	    /* [IN,OUT] 目标链表头 */
        );

/*
 * 链表节点数量
 */
extern int	/* 节点数量 */
listp_count(
        struct listp_link *list_head		/* [IN] 链表头 */
        );

/*----- 通用双向索引链表 -----*/
#define LISTI_HEAD          -1
#define LISTI_TAIL          -1

struct listi_link
{
    int prev, next;
};
typedef struct listi_link listi_link_t;

#define LISTI_LINK(link)  \
struct listi_link link

/*
 * 链表是否为空
 */
#define listi_is_empty(_head)  						            \
((_head)->next == LISTI_TAIL)

/*
 * 链表初始化
 */
#define listi_init(_head)									    \
do                                                              \
{                                                               \
    (_head)->next=(_head)->prev=LISTI_HEAD;                     \
} while(0)

/*
 * 在某个节点后加入新节点
 */
#define listi_add(_head, _array, _link, _new, _v_prev)	  		\
do																\
{																\
    int _prev=_v_prev;                                          \
    int _next;                                                  \
    if((_prev) == LISTI_HEAD)                                   \
    {                                                           \
        _next=(_head)->next;					                \
        (_head)->next=_new;					                    \
    }                                                           \
    else                                                        \
    {                                                           \
        _next=(_array)[_prev]._link.next;					    \
        (_array)[_prev]._link.next=_new;					    \
    }                                                           \
    if(_next == LISTI_TAIL)                                     \
        (_head)->prev=_new;					                    \
    else                                                        \
        (_array)[_next]._link.prev=_new; 		    			\
    (_array)[_new]._link.next=_next;						    \
    (_array)[_new]._link.prev=_prev;		    				\
} while(0)

/*
 * 在链表末加入新节点
 */
#define listi_add_tail(_head, _array, _link, _new)     			\
listi_add(_head, _array, _link, _new, (_head)->prev)

/*
 * 在链表末尾加入整个数组
 */
#define listi_add_array(_head, _array, _link, _size)			\
do																\
{																\
    int _new;													\
    for(_new=0; _new<_size; _new++)		    					\
    {                                                           \
        listi_add_tail(_head, _array, _link, _new);				\
    }                                                           \
} while(0)

/*
 * 从链表中删除节点
 */
#define listi_del(_head, _array, _link, _del)					\
do																\
{																\
    int _prev, _next;											\
    _prev=(_array)[_del]._link.prev;			     			\
    _next=(_array)[_del]._link.next;	    					\
    if(_prev == LISTI_HEAD)                                     \
        (_head)->next=_next;                                    \
    else                                                        \
        (_array)[_prev]._link.next=_next;   					\
    if(_next == LISTI_TAIL)                                     \
        (_head)->prev=_prev;                                    \
    else                                                        \
        (_array)[_next]._link.prev=_prev;			    		\
} while(0)

__END_DECLS

#endif
